/*!
\copyright  Copyright (c) 2023 - 2025 Qualcomm Technologies International, Ltd.\n
            All Rights Reserved.\n
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\file
\brief      USB Audio class 2.0 descriptors
*/

#include "usb_audio_class_20_descriptors.h"
#include "usb_audio_class_20_default_descriptors.h"
#include "usb_audio_defines.h"

static const uint8 control_intf_desc_voice_mic[] =
{
    /* Clock source */
    UAC2_CS_DESC_SIZE,             /* bLength */
    UAC_CS_DESC_INTERFACE,         /* bDescriptorType */
    UAC_AC_DESC_CLOCK_SOURCE,      /* bDescriptorSubType*/
    UAC2_ID_MIC_CLOCK_SOURCE,      /* bClockID */
    UAC2_CS_TYPE_PROGRAMMABLE,     /* bmAttributes */
    UAC2_CS_CONTROL_FREQUENCY |
    UAC2_CS_CONTROL_VALIDITY_READ, /* bmControls */
    0,                             /* bAssocTerminal  */
    0,                             /* iClockSource    */

    /* Microphone IT */
    UAC2_IT_DESC_SIZE,                  /* bLength */
    UAC_CS_DESC_INTERFACE,              /* bDescriptorType = CS_INTERFACE */
    UAC_AC_DESC_INPUT_TERMINAL,         /* bDescriptorSubType = INPUT_TERMINAL */
    UAC2_ID_MIC_VOICE_IT,               /* bTerminalID */
    UAC_TRM_BIDI_HEADSET & 0xFF,        /* wTerminalType = Microphone*/
    UAC_TRM_BIDI_HEADSET >> 8,
    0x00,                               /* bAssocTerminal = none */
    UAC2_ID_MIC_CLOCK_SOURCE,           /* bCSource */
    UAC2_VOICE_MIC_CHANNELS,            /* bNrChannels */

    UAC2_VOICE_MIC_CHANNEL_CONFIG,      /* wChannelConfig  */
    UAC2_VOICE_MIC_CHANNEL_CONFIG >> 8,
    UAC2_VOICE_MIC_CHANNEL_CONFIG >> 16,
    UAC2_VOICE_MIC_CHANNEL_CONFIG >> 24,
    0x00,                               /* iChannelNames */
    0x00,                               /* bmControls*/
    0x00,
    0x00,                               /* iTerminal = same as USB product string */

    /* Microphone Features */
    UAC2_FU_DESC_SIZE(UAC2_VOICE_MIC_CHANNELS),   /*bLength*/
    UAC_CS_DESC_INTERFACE,              /* bDescriptorType = CS_INTERFACE */
    UAC_AC_DESC_FEATURE_UNIT,           /* bDescriptorSubType = FEATURE_UNIT*/
    UAC2_ID_MIC_VOICE_FU,                 /* bUnitId*/
    UAC2_ID_MIC_VOICE_IT,                 /* bSourceId - Microphone IT*/

    UAC2_VOICE_MASTER_CONTROLS, /* bmaControls[1] Master Channel */
    UAC2_VOICE_MASTER_CONTROLS >> 8,
    UAC2_VOICE_MASTER_CONTROLS >> 16,
    UAC2_VOICE_MASTER_CONTROLS >> 24,

    0x00,                       /* bmaControls[2] (Left Front)*/
    0x00,
    0x00,
    0x00,

    #if UAC2_VOICE_MIC_CHANNELS == 2
    0x00,           /* bmaControls[3] (Right Front)*/
    0x00,
    0x00,
    0x00,
    #endif
    0x00,                               /* iFeature = same as USB product string*/

    /* Microphone OT */
    UAC2_OT_DESC_SIZE,                  /* bLength */
    UAC_CS_DESC_INTERFACE,              /* bDescriptorType = CS_INTERFACE */
    UAC_AC_DESC_OUTPUT_TERMINAL,        /* bDescriptorSubType = OUTPUT_TERMINAL */
    UAC2_ID_MIC_VOICE_OT,               /* bTerminalID */
    UAC_TRM_USB_STREAMING & 0xFF,       /* wTerminalType = USB streaming */
    UAC_TRM_USB_STREAMING >> 8,
    0x00,                               /* bAssocTerminal = none */
    UAC2_ID_MIC_VOICE_FU,               /* bSourceID - Microphone Features */
    UAC2_ID_MIC_CLOCK_SOURCE,           /* bCSourceID */
    0x00,/* bmControls */
    0x00,
    0x00,                               /* iTerminal = same as USB product string */
};

static const uint8 control_intf_desc_audio_spkr[] =
{
    /* Clock source */
    UAC2_CS_DESC_SIZE,             /* bLength */
    UAC_CS_DESC_INTERFACE,         /* bDescriptorType */
    UAC_AC_DESC_CLOCK_SOURCE,      /* bDescriptorSubType*/
    UAC2_ID_SPKR_CLOCK_SOURCE,     /* bClockID */
    UAC2_CS_TYPE_PROGRAMMABLE,     /* bmAttributes */
    UAC2_CS_CONTROL_FREQUENCY |
    UAC2_CS_CONTROL_VALIDITY_READ, /* bmControls */
    0,                             /* bAssocTerminal  */
    0,                             /* iClockSource    */

    /* Speaker IT */
    UAC2_IT_DESC_SIZE,                  /* bLength */
    UAC_CS_DESC_INTERFACE,              /* bDescriptorType = CS_INTERFACE */
    UAC_AC_DESC_INPUT_TERMINAL,         /* bDescriptorSubType = INPUT_TERMINAL */
    UAC2_ID_SPKR_AUDIO_IT,              /* bTerminalID */
    (uint8)UAC_TRM_USB_STREAMING,              /* wTerminalType = USB streaming */
    (uint8)(UAC_TRM_USB_STREAMING >> 8),
    0x00,                               /* bAssocTerminal */
    UAC2_ID_SPKR_CLOCK_SOURCE,          /* bCSource */

    UAC2_AUDIO_SPKR_CHANNELS,           /* bNrChannels = 2 */

    UAC2_AUDIO_SPKR_CHANNEL_CONFIG,     /* bmChannelConfig   */
    UAC2_AUDIO_SPKR_CHANNEL_CONFIG >> 8,
    UAC2_AUDIO_SPKR_CHANNEL_CONFIG >> 16,
    UAC2_AUDIO_SPKR_CHANNEL_CONFIG >> 24,

    0x00,                               /* iChannelNames*/
    0x00,                               /* bmControls*/
    0x00,
    0x00,                               /* iTerminal */


    /* Speaker Features */
    UAC2_FU_DESC_SIZE(UAC2_AUDIO_SPKR_CHANNELS),   /*bLength*/
    UAC_CS_DESC_INTERFACE,              /* bDescriptorType = CS_INTERFACE */
    UAC_AC_DESC_FEATURE_UNIT,           /* bDescriptorSubType = FEATURE_UNIT*/
    UAC2_ID_SPKR_AUDIO_FU,              /* bUnitId*/
    UAC2_ID_SPKR_AUDIO_IT,              /* bSourceId */

    UAC2_AUDIO_MASTER_CONTROLS, /* bmaControls[1] Master Channel */
    UAC2_AUDIO_MASTER_CONTROLS >> 8,
    UAC2_AUDIO_MASTER_CONTROLS >> 16,
    UAC2_AUDIO_MASTER_CONTROLS >> 24,

    0x00,                       /* bmaControls[2] (Left Front)*/
    0x00,
    0x00,
    0x00,

    #if UAC2_AUDIO_SPKR_CHANNELS == 2
    0x00,           /* bmaControls[3] (Right Front)*/
    0x00,
    0x00,
    0x00,
    #endif
    0x00,                               /* iFeature = same as USB product string*/


    /* Speaker OT */
    UAC2_OT_DESC_SIZE,                  /* bLength */
    UAC_CS_DESC_INTERFACE,              /* bDescriptorType = CS_INTERFACE */
    UAC_AC_DESC_OUTPUT_TERMINAL,        /* bDescriptorSubType = OUTPUT_TERMINAL */
    UAC2_ID_SPKR_AUDIO_OT,              /* bTerminalID */

    UAC_TRM_OUTPUT_HEADPHONES & 0xFF,   /* wTerminalType */
    UAC_TRM_OUTPUT_HEADPHONES >> 8,

    0x00,                               /* bAssocTerminal = none */
    UAC2_ID_SPKR_AUDIO_FU,              /* bSourceID - Speaker Features*/
    UAC2_ID_SPKR_CLOCK_SOURCE,          /* bCSourceID */

    0x00,/* bmControls */
    0x00,

    0x00                                /* iTerminal = same as USB product string */
};

#define STREAMING_INTF_DESC_VOICE_MIC(sub_slot_size) \
        /* Class Specific AS interface descriptor */                         \
        UAC2_AS_IF_DESC_SIZE,               /* bLength */                    \
        UAC_CS_DESC_INTERFACE,              /* bDescriptorType */            \
        UAC_AS_DESC_GENERAL,                /* bDescriptorSubType */         \
        UAC2_ID_MIC_VOICE_OT,               /* bTerminalLink  */             \
                                                                                \
        0x00, /* bmControls */                                               \
                                                                                \
        UAC_FORMAT_TYPE_I,  /* bFormatType */                                \
                                                                                \
        UAC2_MIC_FORMATS,   /* bmFormats */                                  \
        UAC2_MIC_FORMATS >> 8,                                               \
        UAC2_MIC_FORMATS >> 16,                                              \
        UAC2_MIC_FORMATS >> 24,                                              \
                                                                                \
        UAC2_VOICE_MIC_CHANNELS,          /* bNrChannels */                  \
        UAC2_VOICE_MIC_CHANNEL_CONFIG,    /* bmChannelConfig   */            \
        UAC2_VOICE_MIC_CHANNEL_CONFIG >> 8,                                  \
        UAC2_VOICE_MIC_CHANNEL_CONFIG >> 16,                                 \
        UAC2_VOICE_MIC_CHANNEL_CONFIG >> 24,                                 \
                                                                                \
        0x00, /* iChannelNames */                                            \
                                                                                \
        /* Type 1 format type descriptor */                                  \
        UAC2_FORMAT_1_DESC_SIZE,  /* bLength */                              \
        UAC_CS_DESC_INTERFACE,              /* bDescriptorType = CS_INTERFACE */   \
        UAC_AS_DESC_FORMAT_TYPE,            /* bDescriptorSubType = FORMAT_TYPE */ \
        UAC_FORMAT_TYPE_I,                  /* bFormatType = FORMAT_TYPE_I */      \
        (sub_slot_size),         /* bSubslotSize */                                \
        (sub_slot_size) * 8,      /* bBitResolution */                             \
                                                                                    \
                                                                                    \
        /* Class specific AS isochronous audio data endpoint descriptor */         \
        UAC2_AS_DATA_EP_DESC_SIZE,          /* bLength */                          \
        UAC_CS_DESC_ENDPOINT,               /* bDescriptorType = CS_ENDPOINT */    \
        UAC_AS_EP_DESC_GENERAL,             /* bDescriptorSubType = AS_GENERAL */  \
        0x00,                               /* bmAttributes */                     \
        0x00,                               /* bmControls */                       \
        0x02,                               /* bLockDelayUnits = Decoded PCM samples */ \
        0x00,                               /* wLockDelay */                            \
        0x00

/** Default USB streaming interface descriptors for 16bit mic */
static const uint8 streaming_intf_desc_16bit_voice_mic[] =
{
        STREAMING_INTF_DESC_VOICE_MIC(UAC2_USB_AUDIO_SAMPLE_SIZE_16_BIT)
};

/** Default USB streaming interface descriptors for 24bit mic */
static const uint8 streaming_intf_desc_24bit_voice_mic[] =
{
        STREAMING_INTF_DESC_VOICE_MIC(UAC2_USB_AUDIO_SAMPLE_SIZE_24_BIT)
};

#define STREAMING_INTF_DESC_AUDIO_SPKR(sub_slot_size)                               \
        /* Class Specific AS interface descriptor */                                \
        UAC2_AS_IF_DESC_SIZE,               /* bLength */                           \
        UAC_CS_DESC_INTERFACE,              /* bDescriptorType = CS_INTERFACE */    \
        UAC_AS_DESC_GENERAL,                /* bDescriptorSubType = AS_GENERAL */   \
        UAC2_ID_SPKR_AUDIO_IT,              /* bTerminalLink */                     \
                                                                                    \
        0x00, /* bmControls */                                                      \
                                                            \
        UAC_FORMAT_TYPE_I,  /* bFormatType */            \
                                                            \
        UAC2_SPEAKER_FORMATS, /* bmFormats */            \
        UAC2_SPEAKER_FORMATS >> 8,                       \
        UAC2_SPEAKER_FORMATS >> 16,                      \
        UAC2_SPEAKER_FORMATS >> 24,                      \
                                                            \
        UAC2_AUDIO_SPKR_CHANNELS, /* bNrChannels */                   \
        UAC2_AUDIO_SPKR_CHANNEL_CONFIG,    /* bmChannelConfig   */    \
        UAC2_AUDIO_SPKR_CHANNEL_CONFIG >> 8,                          \
        UAC2_AUDIO_SPKR_CHANNEL_CONFIG >> 16,                         \
        UAC2_AUDIO_SPKR_CHANNEL_CONFIG >> 24,                         \
                                                                        \
        0x00, /* iChannelNames */                                     \
                                                                        \
        /* Type 1 format type descriptor */                                         \
        UAC2_FORMAT_1_DESC_SIZE,  /* bLength */                                     \
        UAC_CS_DESC_INTERFACE,              /* bDescriptorType = CS_INTERFACE */    \
        UAC_AS_DESC_FORMAT_TYPE,            /* bDescriptorSubType = FORMAT_TYPE */  \
        UAC_FORMAT_TYPE_I,          /* bFormatType = FORMAT_TYPE_I */               \
        (sub_slot_size), /* bSubslotSize */                                         \
        (sub_slot_size) * 8, /* bBitResolution */                                   \
                                                                                    \
        /* Class specific AS isochronous audio data endpoint descriptor */              \
        UAC2_AS_DATA_EP_DESC_SIZE,           /* bLength */                              \
        UAC_CS_DESC_ENDPOINT,               /* bDescriptorType = CS_ENDPOINT */         \
        UAC_AS_EP_DESC_GENERAL,             /* bDescriptorSubType = AS_GENERAL */       \
        0x00,                               /* bmAttributes */                          \
        0x00,                               /* bmControls */                            \
        0x02,                               /* bLockDelayUnits = Decoded PCM samples */ \
        0x00,                           /* wLockDelay */                                \
        0x00                                                                            \

/** Default USB streaming interface descriptors for 16bit alt speaker */
static const uint8 streaming_intf_desc_16bit_audio_spkr[] =
{
        STREAMING_INTF_DESC_AUDIO_SPKR(UAC2_USB_AUDIO_SAMPLE_SIZE_16_BIT)
};

/** Default USB streaming interface descriptors for 24bit alt speaker */
static const uint8 streaming_intf_desc_24bit_audio_spkr[] =
{
        STREAMING_INTF_DESC_AUDIO_SPKR(UAC2_USB_AUDIO_SAMPLE_SIZE_24_BIT)
};

/** Default USB streaming interface descriptors for 32bit alt speaker */
static const uint8 streaming_intf_desc_32bit_audio_spkr[] =
{
        STREAMING_INTF_DESC_AUDIO_SPKR(UAC2_USB_AUDIO_SAMPLE_SIZE_32_BIT)
};

/* Voice Mic interface descriptors */
const uac_control_config_t uac2_voice_control_mic_desc = {
    .descriptor = control_intf_desc_voice_mic,
    .size_descriptor = sizeof(control_intf_desc_voice_mic),
};

static const uint32 uac2_voice_mic_frequencies[] = {
        SAMPLE_RATE_8K,
        SAMPLE_RATE_16K,
        SAMPLE_RATE_32K,
};

const uac_clock_source_config_t uac2_voice_mic_clock_sources[] = {
        {
                .clock_source = UAC2_ID_MIC_CLOCK_SOURCE,
                .frequencies = uac2_voice_mic_frequencies,
                .num_frequencies = ARRAY_DIM(uac2_voice_mic_frequencies)
        }
};

const uac_endpoint_config_t uac2_voice_mic_endpoint = {
    .is_to_host = 1,
    .wMaxPacketSize = 0,
    .bInterval = 4 // Service interval 2^(bInterval-1) * 125us
};

const uac_streaming_config_t uac2_voice_streaming_mic_desc[] = {
    {
        &uac2_voice_mic_endpoint,
        streaming_intf_desc_16bit_voice_mic,
        sizeof(streaming_intf_desc_16bit_voice_mic)
    },
    {
        &uac2_voice_mic_endpoint,
        streaming_intf_desc_24bit_voice_mic,
        sizeof(streaming_intf_desc_24bit_voice_mic)
    }
};

/* Audio Speaker interface descriptors */
const uac_control_config_t uac2_music_control_spkr_desc = {
    .descriptor = control_intf_desc_audio_spkr,
    .size_descriptor = sizeof(control_intf_desc_audio_spkr),
};

static const uint32 uac2_music_spkr_frequencies[] = {
        SAMPLE_RATE_8K,
        SAMPLE_RATE_16K,
        SAMPLE_RATE_32K,
        SAMPLE_RATE_44K1,
        SAMPLE_RATE_48K,
        SAMPLE_RATE_96K,
};

const uac_clock_source_config_t uac2_music_spkr_clock_sources[] = {
        {
                .clock_source = UAC2_ID_SPKR_CLOCK_SOURCE,
                .frequencies = uac2_music_spkr_frequencies,
                .num_frequencies = ARRAY_DIM(uac2_music_spkr_frequencies)
        }
};

const uac_endpoint_config_t uac2_music_spkr_endpoint = {
    .is_to_host = 0,
    .wMaxPacketSize = 0,
    .bInterval = 4 // Service interval 2^(bInterval-1) * 125us
};

const uac_streaming_config_t uac2_music_streaming_spkr_desc[] = {
    {
        &uac2_music_spkr_endpoint,
        streaming_intf_desc_16bit_audio_spkr,
        sizeof(streaming_intf_desc_16bit_audio_spkr)
    },
    {
        &uac2_music_spkr_endpoint,
        streaming_intf_desc_24bit_audio_spkr,
        sizeof(streaming_intf_desc_24bit_audio_spkr)
    },
    {
        &uac2_music_spkr_endpoint,
        streaming_intf_desc_32bit_audio_spkr,
        sizeof(streaming_intf_desc_32bit_audio_spkr)
    }
};

static const usb_audio_interface_config_t uac2_music_intf_list[] =
{
    {
        .type = USB_AUDIO_DEVICE_TYPE_AUDIO_SPEAKER,
        .control_desc =   &uac2_music_control_spkr_desc,
        .streaming_config = uac2_music_streaming_spkr_desc,
        .alt_settings_count = ARRAY_DIM(uac2_music_streaming_spkr_desc),

        .clock_sources = uac2_music_spkr_clock_sources,
        .clock_sources_count = ARRAY_DIM(uac2_music_spkr_clock_sources),
    }
};

const usb_audio_interface_config_list_t uac2_music_interfaces =
{
    .intf = uac2_music_intf_list,
    .num_interfaces = ARRAY_DIM(uac2_music_intf_list)
};

/* Audio Speaker Voice Mic interface descriptors */
static const usb_audio_interface_config_t uac2_music_spkr_voice_mic_intf_list[] =
{
    {
        .type = USB_AUDIO_DEVICE_TYPE_VOICE_MIC,
        .control_desc =   &uac2_voice_control_mic_desc,
        .streaming_config = uac2_voice_streaming_mic_desc,
        .alt_settings_count = ARRAY_DIM(uac2_voice_streaming_mic_desc),

        .clock_sources = uac2_voice_mic_clock_sources,
        .clock_sources_count = ARRAY_DIM(uac2_voice_mic_clock_sources)
    },
    {
        .type = USB_AUDIO_DEVICE_TYPE_AUDIO_SPEAKER,
        .control_desc =   &uac2_music_control_spkr_desc,
        .streaming_config = uac2_music_streaming_spkr_desc,
        .alt_settings_count = ARRAY_DIM(uac2_music_streaming_spkr_desc),

        .clock_sources = uac2_music_spkr_clock_sources,
        .clock_sources_count = ARRAY_DIM(uac2_music_spkr_clock_sources)
    }
};

const usb_audio_interface_config_list_t uac2_music_spkr_voice_mic_interfaces =
{
    .intf = uac2_music_spkr_voice_mic_intf_list,
    .num_interfaces = ARRAY_DIM(uac2_music_spkr_voice_mic_intf_list)
};
